﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using Citi.Helpers;

namespace Citi.EmailSender.Domain
{
    public static class Util
    {
        public static string TempFolder { get; set; }
        public static string Proxy { get; set; }
        public static string NetworkDomain { get; set; }
        public static string NetworkUser { get; set; }
        public static string NetWorkPassword { get; set; }
        public static string DownloadTempFolder { get; set; }
        public static string WebUrl { get; set; }

        public static EmailHelper.EmailData FillEmailData(Email email, int index = 0)
        {
            var emailData = new EmailHelper.EmailData
            {
                Bcc = string.Join(";", email.EmailReceivers.Where(x => x.Type == (int)Enums.EmailReceiverType.Bcc).ToList().Select(x => x.EmailAddress.Address)),
                To = string.Join(";", email.EmailReceivers.Where(x => x.Type == (int)Enums.EmailReceiverType.To).ToList().Select(x => x.EmailAddress.Address)),
                Cc = string.Join(";", email.EmailReceivers.Where(x => x.Type == (int)Enums.EmailReceiverType.Cc).ToList().Select(x => x.EmailAddress.Address)),
                BodyMessage = GetEmailBody(email),
                SentOnBehalfOfName = email.EmailData.OnBehalfOf.Email,
                Subject = ReplaceParameters(email.EmailData.Subject, email.EmailParameters),
                Attachments = new List<string>()
            };

            FillAttachments(email, index, emailData);
            return emailData;
        }

        private static string GetEmailBody(Email email)
        {
            if (!string.IsNullOrEmpty(email.EmailData.Body))
                return ReplaceParameters(email.EmailData.Body, email.EmailParameters);

            if (!string.IsNullOrEmpty(email.EmailData.Url))
            {
                int converted = 0;
                var url = !email.EmailData.Url.StartsWith("http") && int.TryParse(email.EmailData.Url.Substring(0, 1), out converted)
                    ? string.Concat(WebUrl, email.EmailData.Url)
                    : email.EmailData.Url;

                var urlReplaced = ReplaceParameters(url, email.EmailParameters);
                return ReplaceParameters(EmailHelper.GetEmailBody(urlReplaced, NetworkUser, NetWorkPassword, NetworkDomain, Proxy), email.EmailParameters);
            }

            return string.Empty;
        }

        private static string ReplaceParameters(string html, IEnumerable<EmailParameter> parameters)
        {
            return parameters.Aggregate(html, (current, parameter) => current.Replace(parameter.EmailDataParameter.Name, parameter.Value));
        }

        private static void FillAttachments(Email email, int index, EmailHelper.EmailData emailData)
        {
            if (email.Attachments == null) return;

            Console.WriteLine("{0} #{1} Attaching files", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), index);

            foreach (var attachment in email.Attachments)
            {
                if (attachment.Path.ToLower().StartsWith("http"))
                {
                    var downloadedFile = Path.Combine(TempFolder, Path.GetFileName(attachment.Path));
                    //client.DownloadFile(attachment.Path, downloadedFile);
                    DownloadRemoteFile(attachment.Path, downloadedFile);
                    emailData.Attachments.Add(downloadedFile);
                }
                else
                    emailData.Attachments.Add(attachment.Path);
            }
        }

        private static void DownloadRemoteFile(string uri, string fileName)
        {
            var request = (HttpWebRequest)WebRequest.Create(uri);
            request.Credentials = new NetworkCredential(NetworkUser, NetWorkPassword, NetworkDomain);

            try
            {
                request.Proxy = new WebProxy(Proxy);
            }
            catch { }
            var response = (HttpWebResponse)request.GetResponse();

            // Check that the remote file was found. The ContentType
            // check is performed since a request for a non-existent
            // image file might be redirected to a 404-page, which would
            // yield the StatusCode "OK", even though the image was not
            // found.
            if ((response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Moved && response.StatusCode != HttpStatusCode.Redirect))
                return;

            // if the remote file was found, download oit
            using (var inputStream = response.GetResponseStream())
            {
                using (var outputStream = File.OpenWrite(fileName))
                {
                    var buffer = new byte[4096];
                    int bytesRead;
                    do
                    {
                        bytesRead = inputStream.Read(buffer, 0, buffer.Length);
                        outputStream.Write(buffer, 0, bytesRead);
                    } while (bytesRead != 0);
                }
            }
        }
    }
}
